package org.jsola.hr.service.impl.syncSoc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jsola.cache.ICache;
import org.jsola.common.ArrayKit;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.*;
import org.jsola.hr.constant.QdWebSiteSocTypeIndex;
import org.jsola.hr.dao.IEmpSocItemDAO;
import org.jsola.hr.dto.SocAccountDTO;
import org.jsola.hr.dto.SyncSocUniversalDTO;
import org.jsola.hr.dto.SyncSocWebSiteDTO;
import org.jsola.hr.dto.syncSocDTO.QdResponseDTO;
import org.jsola.hr.dto.syncSocDTO.QingDaoCardinalityDefaultDTO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.entity.EmpSocInfoDO;
import org.jsola.hr.entity.EmpSocItemDO;
import org.jsola.hr.entity.EmpSocRelatedDO;
import org.jsola.hr.query.SocCheckCustomQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.JiNanSocPaymentDocumentsVO;
import org.jsola.hr.vo.JiNanSocVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.EmpSocStatus.NORMAL_SOC;
import static org.jsola.hr.constant.HrConstants.*;
import static org.jsola.hr.constant.SocPayCostType.NORMAL_PAY_COST;

/**
 * @author lyh
 */
@Service("hrJiNanSyncSocServiceImpl")
@Slf4j
public class JiNanSyncSocServiceImpl implements ISyncSocInterface {

    @Autowired
    private ICache cache;

    @Autowired
    private IEmpSocMonthService empSocMonthService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IEmpSocInfoService empSocInfoService;

    @Autowired
    private IEmpSocItemDAO empSocItemDAO;

    @Autowired
    private IEmpSocItemService empSocItemService;

    @Autowired
    private IEmpSocRelatedService empSocRelatedService;

    @Override
    public List<QdResponseDTO> incrementSocEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return new ArrayList<>();
    }

    @Override
    public List<String> decreaseSocEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return new ArrayList<>();
    }

    @Override
    public int incrementMeEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    public int decreaseMeEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    public int incrementPfEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    public int decreasePfEmp(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return 0;
    }

    @Override
    public List<SyncSocUniversalDTO> batchSyncSocInfo(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        log.info("batchSync-> 开始同步济南社保" + System.currentTimeMillis());
        if (!StringUtils.isEmpty(syncSocWebSiteDTO.getStartDate())) {
            syncSocWebSiteDTO.setStartDate(syncSocWebSiteDTO.getStartDate() + "01000000");
        }
        if (!StringUtils.isEmpty(syncSocWebSiteDTO.getEndDate())) {
            if (Integer.parseInt(syncSocWebSiteDTO.getEndDate().substring(4, 6)) > DateUtils.getCurrentMonth()) {
                throw new ParamException("不能同步未来月份");
            }
            syncSocWebSiteDTO.setEndDate(syncSocWebSiteDTO.getEndDate() + DateUtils.getMonthDayCount(syncSocWebSiteDTO.getEndDate()) + "000000");
        }
        List<SyncSocUniversalDTO> resultList = new ArrayList<>();
        SocAccountDTO socAccountDTO = cache.get(CacheKeyKit.getSocAccount(tokenUser.getUserId(), syncSocWebSiteDTO.getAreaId()));
        if (ObjectUtils.isEmpty(socAccountDTO)) {
            throw new ParamException("请重新登录");
        }
        String usersessionUuid = socAccountDTO.getExtraField().get("usersessionUuid");
        String cookie = socAccountDTO.getCookie();

        // 2：获取dwdjid、jdjgid
        String dwdjidAndJdjgid = JiNanSocialSecurity.getDwdjidAndJdjgid(usersessionUuid, cookie);
        int dwdjidIndex = dwdjidAndJdjgid.indexOf("dwdjid:\"");
        int bizIndex = dwdjidAndJdjgid.lastIndexOf("biz : \"");
        ParamException.isFalse(dwdjidIndex == -1 || bizIndex == -1, "获取dwdjid或jdjgig错误，同步失败，请联系管理员！");
        String dwdjid = dwdjidAndJdjgid.substring(dwdjidIndex + 8, dwdjidIndex + 28);
        String jdjgid = dwdjidAndJdjgid.substring(bizIndex + 7, bizIndex + 15);

        // 3：获取gridSessionID
        String s = JiNanSocialSecurity.getGridSessionId("fwdPageQueryPayBills", dwdjid, jdjgid, usersessionUuid, cookie);
        int gridSessionIndex = s.indexOf("gridSessionID");
        ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID错误，同步失败，请联系管理员！");
        String gridSessionID1 = s.substring(gridSessionIndex + 16, s.indexOf("\",\"onDblClickRow\""));
        // 4: 设置时间参数
        JiNanSocialSecurity.setParameter(dwdjid, jdjgid, usersessionUuid,
                gridSessionID1, syncSocWebSiteDTO.getStartDate(), syncSocWebSiteDTO.getEndDate(), cookie);
        // 5：获取列表
        String list = JiNanSocialSecurity.getList(gridSessionID1, usersessionUuid, cookie);
        JSONObject JSONlist = JSON.parseObject(list);
        JSONArray jsonArray = JSONlist.getJSONArray("rows");
        List<JiNanSocPaymentDocumentsVO> jiNanSocPaymentDocumentsVOList = new ArrayList<>();
        for (Object o : jsonArray) {
            JSONObject paymentDocuments = JSON.parseObject(o.toString());
            // 获取流水号及其相关时间
            JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO = JSON.toJavaObject(paymentDocuments, JiNanSocPaymentDocumentsVO.class);
            jiNanSocPaymentDocumentsVOList.add(jiNanSocPaymentDocumentsVO);
        }
        log.info("batchSync-> 获取社保流水号" + System.currentTimeMillis());
        log.info("batchSync-> 共有{}条流水", jiNanSocPaymentDocumentsVOList.size());
        String cardinalityDefaultStr =
                JiNanSocialSecurity.getGridSessionId("fwdOrgnRateVAPAllNow", dwdjid, jdjgid, usersessionUuid, cookie);
        int cardinalityDefaultGridSessionIndex = cardinalityDefaultStr.indexOf("gridSessionID");
        ParamException.isFalse(cardinalityDefaultGridSessionIndex == -1, "获取gridSessionID错误，同步失败，请联系管理员！");
        String cardinalityDefaultGridSession =
                cardinalityDefaultStr.substring(cardinalityDefaultGridSessionIndex + 16, cardinalityDefaultStr.indexOf("\",\"paddingRight\""));
        // 拿到基数
        Map<String, QingDaoCardinalityDefaultDTO> cardinalityDefaultMap =
                getCardinalityDefault(usersessionUuid, cookie, cardinalityDefaultGridSession);
        log.info("batchSync-> 获取社保相关基数" + System.currentTimeMillis());
        // 6:根据流水号查询个人缴费明细
        String monthId;
        List<SyncSocUniversalDTO> paymentDetailsList;
        for (JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO : jiNanSocPaymentDocumentsVOList) {
            paymentDetailsList = new ArrayList<>();
            // 根据流水号查询个人缴费明细
            String serialNumberId = jiNanSocPaymentDocumentsVO.getZdlsh();
            // 设置参数
            String param = JiNanSocialSecurity.selectParameterBySerialNumberId(jdjgid, serialNumberId, usersessionUuid, cookie);
            // 重新获取参数：gridSessionId
            String gridSessionID2 = JiNanSocialSecurity.getGridSessionId2(serialNumberId, jdjgid, usersessionUuid, cookie);
            gridSessionIndex = gridSessionID2.lastIndexOf("gridSessionID");
            ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID2错误，同步失败，请联系管理员！");
            gridSessionID2 = gridSessionID2.substring(gridSessionIndex + 16, gridSessionIndex + 16 + 53);
            // 查询列表
            list = JiNanSocialSecurity.selectPaymentDetailsBySerialNumberId(param, gridSessionID2, usersessionUuid,
                    cookie, 1, 25);
            JSONObject JSONlist2 = JSON.parseObject(list);
            JSONArray jsonArray2 = JSONlist2.getJSONArray("rows");
            Integer total = JSONlist2.getInteger("total");
            int maxPage = (total + 25 - 1) / 25;
            for (Object o : jsonArray2) {
                JSONObject paymentDocuments = JSON.parseObject(o.toString());
                JiNanSocVO jiNanSocVO = JSON.toJavaObject(paymentDocuments, JiNanSocVO.class);
                paymentDetailsList.add(BeanCopyUtil.beanCopy(jiNanSocVO, SyncSocUniversalDTO.class));
            }
            log.info("batchSync-> 获取社保第一页数据" + System.currentTimeMillis());
            for (int i = 2; i <= maxPage; i++) {
                list = JiNanSocialSecurity.selectPaymentDetailsBySerialNumberId(param, gridSessionID2, usersessionUuid,
                        cookie, i, 25);
                JSONObject pageDateJson = JSON.parseObject(list);
                JSONArray pageDate = pageDateJson.getJSONArray("rows");
                for (Object date : pageDate) {
                    JSONObject paymentDocuments = JSON.parseObject(date.toString());
                    JiNanSocVO jiNanSocVO = JSON.toJavaObject(paymentDocuments, JiNanSocVO.class);
                    paymentDetailsList.add(BeanCopyUtil.beanCopy(jiNanSocVO, SyncSocUniversalDTO.class));
                }
                log.info("batchSync-> 获取社保第{}页数据" + System.currentTimeMillis(), i);
            }
            log.info("batchSync-> 获取社保其他页数据" + System.currentTimeMillis());
            if (paymentDetailsList.size() == 0) {
                continue;
            }
            log.info("batchSync-> 查询数据列表" + System.currentTimeMillis());
            parseSyncSocUniversalDTOList(paymentDetailsList);
            // 查询monthid
            String[] yearAndMonth = DateUtils.getYearAndMonthByDateString(jiNanSocPaymentDocumentsVO.getQrsj().substring(0, 6));
            monthId = empSocMonthService.selectMonthIdByYearAndMonth(syncSocWebSiteDTO.getCompanyId(), yearAndMonth[0],
                    yearAndMonth[1], tokenUser.getSiteId());
            if (StringUtils.isEmpty(monthId)) {
                monthId = empSocMonthService
                        .saveByYearAndMonth(syncSocWebSiteDTO.getCompanyId(), yearAndMonth[0], yearAndMonth[1], tokenUser)
                        .getId();
            }
            // 按照姓名分组
            Map<String, List<SyncSocUniversalDTO>> paymentDetailsName =
                    paymentDetailsList.stream().collect(Collectors.groupingBy(SyncSocUniversalDTO::getEmpName));
            // 查询员工
            for (String empNameKey : paymentDetailsName.keySet()) {
                List<SyncSocUniversalDTO> paymentDetails = paymentDetailsName.get(empNameKey);
                // 查询花名册有无此人
                EmpInfoDO empInfoDO = empInfoService.selectEmpByNameAndIdCard(paymentDetails.get(0).getEmpName(),
                        paymentDetails.get(0).getIdCard(), syncSocWebSiteDTO.getCompanyId(), tokenUser);
                if (ObjectUtils.isEmpty(empInfoDO)) {
                    continue;
                }
                EmpSocRelatedDO empSocRelatedDO = empSocRelatedService.selectByEmpId(empInfoDO.getId(), tokenUser.getSiteId());
                if (ObjectUtils.isEmpty(empSocRelatedDO.getSocIncreaseDate())) {
                    empSocRelatedDO.setSocIncreaseDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empSocRelatedDO.setSocState(NORMAL_SOC.getValue());
                    empSocRelatedService.updateByIdSelective(empSocRelatedDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                if (ObjectUtils.isEmpty(empInfoDO.getSocDate())) {
                    empInfoDO.setSocDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empInfoDO.setEmpSocStatus(NORMAL_SOC.getValue());
                    empInfoService.updateByIdSelective(empInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                // 查询某个参保月中的某一个人的一条正常参保的记录
                String empSocInfoId;
                EmpSocInfoDO empSocInfoDO = empSocInfoService.selectEmpSocInfoByEmpIdAndMonthIdNormal(monthId,
                        empInfoDO.getId(), syncSocWebSiteDTO.getCompanyId(), tokenUser);
                // 删除旧的数据
                if (!ObjectUtils.isEmpty(empSocInfoDO)) {
                    empSocInfoId = empSocInfoDO.getId();
                    List<EmpSocItemDO> empSocItemDelete = empSocItemService.selectByEmpSocIdAndItemType(empSocInfoId,
                            SOC_ITEM_TYPE, tokenUser.getSiteId());
                    if (!CollectionUtils.isEmpty(empSocItemDelete)) {
                        empSocItemService.deleteByDoList(empSocItemDelete);
                    }
                } else {
                    empSocInfoDO = new EmpSocInfoDO();
                    empSocInfoService.syncFillEmpSocInfo(empSocInfoDO, monthId, yearAndMonth[0], yearAndMonth[1],
                            syncSocWebSiteDTO.getCompanyId(), empInfoDO.getId(), NORMAL_PAY_COST.getDesc());
                    EmpSocInfoDO result = empSocInfoService.save(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                    empSocInfoId = result.getId();
                }
                // 新增该人员的对应社保数据
                List<EmpSocItemDO> empSocItemList = new ArrayList<>();
                // 个人社保金额,公司社保金额
                BigDecimal personalSocAmount = new BigDecimal("0");
                BigDecimal companySocAmount = new BigDecimal("0");
                for (SyncSocUniversalDTO syncSocUniversalDTO : paymentDetails) {
                    BigDecimal[] bigDecimals = empSocItemService.syncFillEmpSocInfoItem(
                            syncSocUniversalDTO.getItemName(),
                            empSocInfoId, syncSocUniversalDTO.getCardinalityDefault(), syncSocUniversalDTO.getAmountCompany(),
                            syncSocUniversalDTO.getAmountPersonal(), null, null, empSocItemList,
                            cardinalityDefaultMap, 1, tokenUser);
                    personalSocAmount = personalSocAmount.add(bigDecimals[1]);
                    companySocAmount = companySocAmount.add(bigDecimals[0]);
                    resultList.add(syncSocUniversalDTO);
                }
                empSocInfoDO.setPersonalSocAmount(personalSocAmount);
                empSocInfoDO.setCompanySocAmount(companySocAmount);
                if (ObjectUtils.isEmpty(empSocInfoDO.getCompanyPfAmount())) {
                    empSocInfoDO.setCompanyPfAmount(new BigDecimal("0"));
                }
                if (ObjectUtils.isEmpty(empSocInfoDO.getPersonalPfAmount())) {
                    empSocInfoDO.setPersonalPfAmount(new BigDecimal("0"));
                }
                empSocInfoService.updateByIdSelective(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                empSocItemDAO.insertListAndSetId(empSocItemList);
            }
        }
        log.info("batchSync-> 结束同步济南社保" + System.currentTimeMillis());
        return resultList;
    }

    @Override
    public List<SyncSocUniversalDTO> batchSyncMeInfo(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        log.info("batchSync-> 开始同步济南医保" + System.currentTimeMillis());
        List<SyncSocUniversalDTO> resultList = new ArrayList<>();
        if (!StringUtils.isEmpty(syncSocWebSiteDTO.getStartDate()) && syncSocWebSiteDTO.getStartDate().length() == 6) {
            syncSocWebSiteDTO.setStartDate(syncSocWebSiteDTO.getStartDate() + "01000000");
        }
        if (!StringUtils.isEmpty(syncSocWebSiteDTO.getEndDate())) {
            if (Integer.parseInt(syncSocWebSiteDTO.getEndDate().substring(4, 6)) > DateUtils.getCurrentMonth()) {
                throw new ParamException("不能同步未来月份");
            }
            if (syncSocWebSiteDTO.getEndDate().length() == 6) {
                syncSocWebSiteDTO.setEndDate(syncSocWebSiteDTO.getEndDate() + DateUtils.getMonthDayCount(syncSocWebSiteDTO.getEndDate()) + "000000");
            }
        }
        SocAccountDTO socAccountDTO = cache.get(CacheKeyKit.getMeAccount(tokenUser.getUserId(), syncSocWebSiteDTO.getAreaId()));
        if (ObjectUtils.isEmpty(socAccountDTO)) {
            throw new ParamException("请重新登录");
        }

        String usersessionUuid = socAccountDTO.getExtraField().get("usersessionUuid");
        String cookie = socAccountDTO.getCookie();
        // 2：获取dwdjid、jdjgid
        String dwdjidAndJdjgid = JiNanMedicalInsurance.getDwdjidAndJdjgid(usersessionUuid, cookie);
        int nums = dwdjidAndJdjgid.indexOf("fwdFunctionByParent(");
        int latas = dwdjidAndJdjgid.indexOf(");    })\">医疗保险申报");
        ParamException.isFalse(nums == -1 || latas == -1, "获取dwdjid或jdjgig错误，同步失败，请联系管理员！");
        List<String> all1 = ArrayKit.split(dwdjidAndJdjgid.substring(nums + 21, latas), "','");
        ParamException.isFalse(all1 == null || all1.size() < 5, "获取dwdjid或jdjgig错误，同步失败，请联系管理员！");
        String dwdjid = all1.get(0);
        String jdjgid = all1.get(4);

        // 3：获取gridSessionID
        String s = JiNanMedicalInsurance.getGridSessionId("fwdPageQueryPayBills", dwdjid, jdjgid, usersessionUuid, cookie);
        int gridSessionIndex = s.indexOf("gridSessionID");
        ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID错误，同步失败，请联系管理员！");
        String gridSessionID1 = s.substring(gridSessionIndex + 16, s.indexOf("\",\"onDblClickRow\""));
        // 4: 设置时间参数
        JiNanMedicalInsurance.setParameter(dwdjid, jdjgid, usersessionUuid, gridSessionID1,
                syncSocWebSiteDTO.getStartDate(), syncSocWebSiteDTO.getEndDate(), cookie);
        // 5：获取列表
        String list = JiNanMedicalInsurance.getList(gridSessionID1, usersessionUuid, cookie);
        com.alibaba.fastjson.JSONObject JSONlist = com.alibaba.fastjson.JSON.parseObject(list);
        com.alibaba.fastjson.JSONArray jsonArray = JSONlist.getJSONArray("rows");
        List<JiNanSocPaymentDocumentsVO> jiNanSocPaymentDocumentsVOList = new ArrayList<>();
        for (Object o : jsonArray) {
            com.alibaba.fastjson.JSONObject paymentDocuments = com.alibaba.fastjson.JSON.parseObject(o.toString());
            // 获取流水号及其相关时间
            JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO = com.alibaba.fastjson.JSON.toJavaObject(paymentDocuments, JiNanSocPaymentDocumentsVO.class);
            jiNanSocPaymentDocumentsVOList.add(jiNanSocPaymentDocumentsVO);
        }
        log.info("batchSync-> 获取医保流水号" + System.currentTimeMillis());
        String cardinalityDefaultStr =
                JiNanMedicalInsurance.getGridSessionId("fwdOrgnRateVAPAllNow", dwdjid, jdjgid, usersessionUuid, cookie);
        int cardinalityDefaultGridSessionIndex = cardinalityDefaultStr.indexOf("gridSessionID");
        ParamException.isFalse(cardinalityDefaultGridSessionIndex == -1, "获取gridSessionID错误，同步失败，请联系管理员！");
        String cardinalityDefaultGridSession =
                cardinalityDefaultStr.substring(cardinalityDefaultGridSessionIndex + 16, cardinalityDefaultStr.indexOf("\",\"paddingRight\""));
        // 拿到基数
        Map<String, QingDaoCardinalityDefaultDTO> cardinalityDefaultMap = getCardinalityDefault(usersessionUuid, cookie, cardinalityDefaultGridSession);
        // 6:根据流水号查询个人缴费明细
        String monthId;
        List<SyncSocUniversalDTO> paymentDetailsList;
        for (JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO : jiNanSocPaymentDocumentsVOList) {
            paymentDetailsList = new ArrayList<>();
            String serialNumberId = jiNanSocPaymentDocumentsVO.getZdlsh();
            // 设置参数
            String param = JiNanMedicalInsurance.selectParameterBySerialNumberId(jdjgid, serialNumberId, usersessionUuid, cookie);
            // 重新获取参数：gridSessionId
            String gridSessionID2 = JiNanMedicalInsurance.getGridSessionId2(serialNumberId, jdjgid, usersessionUuid, cookie);
            gridSessionIndex = gridSessionID2.lastIndexOf("gridSessionID");
            ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID2错误，同步失败，请联系管理员！");
            gridSessionID2 = gridSessionID2.substring(gridSessionIndex + 16, gridSessionIndex + 16 + 36);
            // 查询列表
            list = JiNanMedicalInsurance.selectPaymentDetailsBySerialNumberId(param, gridSessionID2, usersessionUuid,
                    cookie, 1, 25);
            com.alibaba.fastjson.JSONObject JSONlist2 = com.alibaba.fastjson.JSON.parseObject(list);
            com.alibaba.fastjson.JSONArray jsonArray2 = JSONlist2.getJSONArray("rows");
            Integer total = JSONlist2.getInteger("total");
            int maxPage = (total + 25 - 1) / 25;
            for (Object o : jsonArray2) {
                JSONObject paymentDocuments = JSON.parseObject(o.toString());
                JiNanSocVO jiNanSocVO = JSON.toJavaObject(paymentDocuments, JiNanSocVO.class);
                paymentDetailsList.add(BeanCopyUtil.beanCopy(jiNanSocVO, SyncSocUniversalDTO.class));
            }
            for (int i = 2; i <= maxPage; i++) {
                list = JiNanMedicalInsurance.selectPaymentDetailsBySerialNumberId(param, gridSessionID2, usersessionUuid,
                        cookie, i, 25);
                JSONObject pageDateJson = JSON.parseObject(list);
                JSONArray pageDate = pageDateJson.getJSONArray("rows");
                for (Object date : pageDate) {
                    JSONObject paymentDocuments = JSON.parseObject(date.toString());
                    JiNanSocVO jiNanSocVO = JSON.toJavaObject(paymentDocuments, JiNanSocVO.class);
                    paymentDetailsList.add(BeanCopyUtil.beanCopy(jiNanSocVO, SyncSocUniversalDTO.class));
                }
            }
            if (paymentDetailsList.size() == 0) {
                continue;
            }
            log.info("batchSync-> 查询医保数据列表" + System.currentTimeMillis());
            parseSyncSocUniversalDTOList(paymentDetailsList);
            // 查询monthid
            String[] yearAndMonth = DateUtils.getYearAndMonthByDateString(jiNanSocPaymentDocumentsVO.getTxsj().substring(0, 6));
            monthId = empSocMonthService.selectMonthIdByYearAndMonth(syncSocWebSiteDTO.getCompanyId(), yearAndMonth[0],
                    yearAndMonth[1], tokenUser.getSiteId());
            if (StringUtils.isEmpty(monthId)) {
                monthId = empSocMonthService
                        .saveByYearAndMonth(syncSocWebSiteDTO.getCompanyId(), yearAndMonth[0], yearAndMonth[1], tokenUser)
                        .getId();
            }
            // 按照姓名分组
            Map<String, List<SyncSocUniversalDTO>> paymentDetailsName =
                    paymentDetailsList.stream().collect(Collectors.groupingBy(SyncSocUniversalDTO::getEmpName));
            // 查询员工
            for (String empNameKey : paymentDetailsName.keySet()) {
                List<SyncSocUniversalDTO> paymentDetails = paymentDetailsName.get(empNameKey);
                // 查询花名册有无此人
                EmpInfoDO empInfoDO = empInfoService.selectEmpByNameAndIdCard(paymentDetails.get(0).getEmpName(),
                        paymentDetails.get(0).getIdCard(), syncSocWebSiteDTO.getCompanyId(), tokenUser);
                if (ObjectUtils.isEmpty(empInfoDO)) {
                    continue;
                }
                EmpSocRelatedDO empSocRelatedDO = empSocRelatedService.selectByEmpId(empInfoDO.getId(), tokenUser.getSiteId());
                if (ObjectUtils.isEmpty(empSocRelatedDO.getMeIncreaseDate())) {
                    empSocRelatedDO.setMeIncreaseDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empSocRelatedDO.setMeState(NORMAL_SOC.getValue());
                    empSocRelatedService.updateByIdSelective(empSocRelatedDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                if (ObjectUtils.isEmpty(empInfoDO.getSocDate())) {
                    empInfoDO.setSocDate(DateUtils.getDateByDateStr(syncSocWebSiteDTO.getStartDate()));
                    empInfoDO.setEmpSocStatus(NORMAL_SOC.getValue());
                    empInfoService.updateByIdSelective(empInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                }
                // 查询某个参保月中的某一个人的一条正常参保的记录
                String empSocInfoId;
                EmpSocInfoDO empSocInfoDO = empSocInfoService.selectEmpSocInfoByEmpIdAndMonthIdNormal(monthId,
                        empInfoDO.getId(), syncSocWebSiteDTO.getCompanyId(), tokenUser);
                // 删除旧的数据
                if (!ObjectUtils.isEmpty(empSocInfoDO)) {
                    empSocInfoId = empSocInfoDO.getId();
                    List<EmpSocItemDO> empSocItemDelete = empSocItemService.selectByEmpSocIdAndItemType(empSocInfoId,
                            ME_ITEM_TYPE, tokenUser.getSiteId());
                    if (!CollectionUtils.isEmpty(empSocItemDelete)) {
                        empSocItemService.deleteByDoList(empSocItemDelete);
                    }
                } else {
                    empSocInfoDO = new EmpSocInfoDO();
                    empSocInfoService.syncFillEmpSocInfo(empSocInfoDO, monthId, yearAndMonth[0], yearAndMonth[1],
                            syncSocWebSiteDTO.getCompanyId(), empInfoDO.getId(), NORMAL_PAY_COST.getDesc());
                    EmpSocInfoDO result = empSocInfoService.save(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                    empSocInfoId = result.getId();
                }
                // 新增该人员的对应社保数据
                List<EmpSocItemDO> empSocItemList = new ArrayList<>();
                // 个人社保金额,公司社保金额
                BigDecimal personalSocAmount = new BigDecimal("0");
                BigDecimal companySocAmount = new BigDecimal("0");
                for (SyncSocUniversalDTO syncSocUniversalDTO : paymentDetails) {
                    BigDecimal[] bigDecimals = empSocItemService.syncFillEmpSocInfoItem(
                            syncSocUniversalDTO.getItemName(),
                            empSocInfoId, syncSocUniversalDTO.getCardinalityDefault(), syncSocUniversalDTO.getAmountCompany(),
                            syncSocUniversalDTO.getAmountPersonal(), null, null, empSocItemList,
                            cardinalityDefaultMap, 3, tokenUser);
                    personalSocAmount = personalSocAmount.add(bigDecimals[1]);
                    companySocAmount = companySocAmount.add(bigDecimals[0]);
                    resultList.add(syncSocUniversalDTO);
                }
                if (ObjectUtils.isEmpty(empSocInfoDO.getPersonalSocAmount())) {
                    empSocInfoDO.setPersonalSocAmount(personalSocAmount);
                } else {
                    empSocInfoDO.setPersonalSocAmount(empSocInfoDO.getPersonalSocAmount().add(personalSocAmount));
                }
                if (ObjectUtils.isEmpty(empSocInfoDO.getCompanySocAmount())) {
                    empSocInfoDO.setCompanySocAmount(companySocAmount);
                } else {
                    empSocInfoDO.setCompanySocAmount(empSocInfoDO.getCompanySocAmount().add(companySocAmount));
                }
                if (ObjectUtils.isEmpty(empSocInfoDO.getCompanyPfAmount())) {
                    empSocInfoDO.setCompanyPfAmount(new BigDecimal("0"));
                }
                if (ObjectUtils.isEmpty(empSocInfoDO.getPersonalPfAmount())) {
                    empSocInfoDO.setPersonalPfAmount(new BigDecimal("0"));
                }
                empSocInfoService.updateByIdSelective(empSocInfoDO, tokenUser.getSiteId(), tokenUser.getUserId());
                empSocItemDAO.insertListAndSetId(empSocItemList);
            }
        }
        log.info("batchSync-> 结束同步济南医保" + System.currentTimeMillis());
        return resultList;
    }

    @Override
    public List<SyncSocUniversalDTO> batchSyncPfInfo(SyncSocWebSiteDTO syncSocWebSiteDTO, TokenUser tokenUser) {
        return new ArrayList<>();
    }

    @Override
    public Map<String, List<SyncSocUniversalDTO>> checkInfo(SocCheckCustomQuery socCheckCustomQuery, TokenUser tokenUser) {
        String checkDateStr = socCheckCustomQuery.getYear() + socCheckCustomQuery.getMonth();
        if (Integer.parseInt(socCheckCustomQuery.getMonth()) > DateUtils.getCurrentMonth()) {
            throw new ParamException("不能同步未来月份");
        }
        String startDate = checkDateStr + "01000000";
        String endDate = checkDateStr + DateUtils.getMonthDayCount(checkDateStr) + "000000";
        Map<String, List<SyncSocUniversalDTO>> result = new HashMap<>(8);
        if (socCheckCustomQuery.getSocIsTrue()) {
            SocAccountDTO socAccountDTO =
                    cache.get(CacheKeyKit.getSocAccount(tokenUser.getUserId(), socCheckCustomQuery.getAreaId()));
            if (ObjectUtils.isEmpty(socAccountDTO)) {
                throw new ParamException("社保网站未登录或已过期,请重新登录或刷新社保网站");
            }
            String userSessionUuid = socAccountDTO.getExtraField().get("usersessionUuid");
            String cookie = socAccountDTO.getCookie();
            // 2：获取dwdjid、jdjgid
            String dwdjidAndJdjgid = JiNanSocialSecurity.getDwdjidAndJdjgid(userSessionUuid, cookie);
            int dwdjidIndex = dwdjidAndJdjgid.indexOf("dwdjid:\"");
            int bizIndex = dwdjidAndJdjgid.lastIndexOf("biz : \"");
            ParamException.isFalse(dwdjidIndex == -1 || bizIndex == -1, "获取dwdjid或jdjgig错误，同步失败，请联系管理员！");
            String dwdjid = dwdjidAndJdjgid.substring(dwdjidIndex + 8, dwdjidIndex + 28);
            String jdjgid = dwdjidAndJdjgid.substring(bizIndex + 7, bizIndex + 15);
            // 3：获取gridSessionID
            String s = JiNanSocialSecurity.getGridSessionId("fwdPageQueryPayBills", dwdjid, jdjgid, userSessionUuid, cookie);
            int gridSessionIndex = s.indexOf("gridSessionID");
            ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID错误，同步失败，请联系管理员！");
            String gridSessionID1 = s.substring(gridSessionIndex + 16, s.indexOf("\",\"onDblClickRow\""));
            // 4: 设置时间参数
            JiNanSocialSecurity.setParameter(dwdjid, jdjgid, userSessionUuid, gridSessionID1, startDate, endDate, cookie);
            // 5：获取列表
            String list = JiNanSocialSecurity.getList(gridSessionID1, userSessionUuid, cookie);
            JSONObject JSONList = JSON.parseObject(list);
            JSONArray jsonArray = JSONList.getJSONArray("rows");
            List<JiNanSocPaymentDocumentsVO> jiNanSocPaymentDocumentsVOList = new ArrayList<>();
            for (Object o : jsonArray) {
                JSONObject paymentDocuments = JSON.parseObject(o.toString());
                // 获取流水号及其相关时间
                JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO = JSON.toJavaObject(paymentDocuments, JiNanSocPaymentDocumentsVO.class);
                jiNanSocPaymentDocumentsVOList.add(jiNanSocPaymentDocumentsVO);
            }
            if (!CollectionUtils.isEmpty(jiNanSocPaymentDocumentsVOList)) {
                JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO = jiNanSocPaymentDocumentsVOList.get(0);
                // 根据流水号查询个人缴费明细
                String serialNumberId = jiNanSocPaymentDocumentsVO.getZdlsh();
                // 设置参数
                String param = JiNanSocialSecurity.selectParameterBySerialNumberId(jdjgid, serialNumberId, userSessionUuid, cookie);
                // 重新获取参数：gridSessionId
                String gridSessionID2 = JiNanSocialSecurity.getGridSessionId2(serialNumberId, jdjgid, userSessionUuid, cookie);
                gridSessionIndex = gridSessionID2.lastIndexOf("gridSessionID");
                ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID2错误，同步失败，请联系管理员！");
                gridSessionID2 = gridSessionID2.substring(gridSessionIndex + 16, gridSessionIndex + 16 + 53);
                // 查询列表
                list = JiNanSocialSecurity.selectPaymentDetailsBySerialNumberId(param, gridSessionID2, userSessionUuid, cookie, 1, 25);
                JSONObject JSONlist2 = JSON.parseObject(list);
                JSONArray jsonArray2 = JSONlist2.getJSONArray("rows");
                List<SyncSocUniversalDTO> paymentDetailsList = new ArrayList<>();
                for (Object o : jsonArray2) {
                    JSONObject paymentDocuments = JSON.parseObject(o.toString());
                    JiNanSocVO jiNanSocVO = JSON.toJavaObject(paymentDocuments, JiNanSocVO.class);
                    paymentDetailsList.add(BeanCopyUtil.beanCopy(jiNanSocVO, SyncSocUniversalDTO.class));
                }
                if (paymentDetailsList.size() == 0) {
                    result.put(SOC, new ArrayList<>());
                } else {
                    parseSyncSocUniversalDTOList(paymentDetailsList);
                    result.put(SOC, paymentDetailsList);
                }
            } else {
                result.put(SOC, new ArrayList<>());
            }
        }
        if (socCheckCustomQuery.getMeIsTrue()) {
            SocAccountDTO socAccountDTO =
                    cache.get(CacheKeyKit.getMeAccount(tokenUser.getUserId(), socCheckCustomQuery.getAreaId()));
            if (ObjectUtils.isEmpty(socAccountDTO)) {
                throw new ParamException("医保网站未登录或已过期,请重新登录或刷新医保网站");
            }
            String userSessionUuid = socAccountDTO.getExtraField().get("usersessionUuid");
            String cookie = socAccountDTO.getCookie();
            // 2：获取dwdjid、jdjgid
            String dwdjidAndJdjgid = JiNanMedicalInsurance.getDwdjidAndJdjgid(userSessionUuid, cookie);
            int nums = dwdjidAndJdjgid.indexOf("fwdFunctionByParent(");
            int latas = dwdjidAndJdjgid.indexOf(");    })\">医疗保险申报");
            ParamException.isFalse(nums == -1 || latas == -1, "获取dwdjid或jdjgig错误，同步失败，请联系管理员！");
            List<String> all1 = ArrayKit.split(dwdjidAndJdjgid.substring(nums + 21, latas), "','");
            ParamException.isFalse(all1 == null || all1.size() < 5, "获取dwdjid或jdjgig错误，同步失败，请联系管理员！");
            String dwdjid = all1.get(0);
            String jdjgid = all1.get(4);
            // 3：获取gridSessionID
            String s = JiNanMedicalInsurance.getGridSessionId("fwdPageQueryPayBills", dwdjid, jdjgid, userSessionUuid, cookie);
            int gridSessionIndex = s.indexOf("gridSessionID");
            ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID错误，同步失败，请联系管理员！");
            String gridSessionID1 = s.substring(gridSessionIndex + 16, s.indexOf("\",\"onDblClickRow\""));
            // 4: 设置时间参数
            JiNanMedicalInsurance.setParameter(dwdjid, jdjgid, userSessionUuid, gridSessionID1, startDate, endDate, cookie);
            // 5：获取列表
            String list = JiNanMedicalInsurance.getList(gridSessionID1, userSessionUuid, cookie);
            com.alibaba.fastjson.JSONObject JSONlist = com.alibaba.fastjson.JSON.parseObject(list);
            com.alibaba.fastjson.JSONArray jsonArray = JSONlist.getJSONArray("rows");
            List<JiNanSocPaymentDocumentsVO> jiNanSocPaymentDocumentsVOList = new ArrayList<>();
            for (Object o : jsonArray) {
                com.alibaba.fastjson.JSONObject paymentDocuments = com.alibaba.fastjson.JSON.parseObject(o.toString());
                // 获取流水号及其相关时间
                JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO = com.alibaba.fastjson.JSON.toJavaObject(paymentDocuments, JiNanSocPaymentDocumentsVO.class);
                jiNanSocPaymentDocumentsVOList.add(jiNanSocPaymentDocumentsVO);
            }
            if (!CollectionUtils.isEmpty(jiNanSocPaymentDocumentsVOList)) {
                List<SyncSocUniversalDTO> paymentDetailsList = new ArrayList<>();
                JiNanSocPaymentDocumentsVO jiNanSocPaymentDocumentsVO = jiNanSocPaymentDocumentsVOList.get(0);
                String serialNumberId = jiNanSocPaymentDocumentsVO.getZdlsh();
                // 设置参数
                String param = JiNanMedicalInsurance.selectParameterBySerialNumberId(jdjgid, serialNumberId, userSessionUuid, cookie);
                // 重新获取参数：gridSessionI
                String gridSessionID2 = JiNanMedicalInsurance.getGridSessionId2(serialNumberId, jdjgid, userSessionUuid, cookie);
                gridSessionIndex = gridSessionID2.lastIndexOf("gridSessionID");
                ParamException.isFalse(gridSessionIndex == -1, "获取gridSessionID2错误，同步失败，请联系管理员！");
                gridSessionID2 = gridSessionID2.substring(gridSessionIndex + 16, gridSessionIndex + 16 + 36);
                // 查询列表
                list = JiNanMedicalInsurance.selectPaymentDetailsBySerialNumberId(param, gridSessionID2, userSessionUuid, cookie, 1, 25);
                com.alibaba.fastjson.JSONObject JSONList2 = com.alibaba.fastjson.JSON.parseObject(list);
                com.alibaba.fastjson.JSONArray jsonArray2 = JSONList2.getJSONArray("rows");
                for (Object o : jsonArray2) {
                    JSONObject paymentDocuments = JSON.parseObject(o.toString());
                    JiNanSocVO jiNanSocVO = JSON.toJavaObject(paymentDocuments, JiNanSocVO.class);
                    paymentDetailsList.add(BeanCopyUtil.beanCopy(jiNanSocVO, SyncSocUniversalDTO.class));
                }
                if (paymentDetailsList.size() == 0) {
                    result.put(ME, new ArrayList<>());
                } else {
                    parseSyncSocUniversalDTOList(paymentDetailsList);
                    result.put(ME, paymentDetailsList);
                }
            } else {
                result.put(ME, new ArrayList<>());
            }
        }
        if (socCheckCustomQuery.getPfIsTrue()) {
            result.put(PF, new ArrayList<>());
        }
        return result;
    }


    private void parseSyncSocUniversalDTOList(List<SyncSocUniversalDTO> syncSocUniversalDTOList) {
        for (SyncSocUniversalDTO syncSocUniversalDTO : syncSocUniversalDTOList) {
            syncSocUniversalDTO.setItemName(QdWebSiteSocTypeIndex.find(syncSocUniversalDTO.getItemName()).getDesc());
            if ("A01".equals(syncSocUniversalDTO.getPayCostType())) {
                syncSocUniversalDTO.setPayCostType(NORMAL_PAY_COST.getDesc());
            }
        }
    }

    private Map<String, QingDaoCardinalityDefaultDTO> getCardinalityDefault(String usersessionUuid, String cookie, String gridSessionID) {
        List<QingDaoCardinalityDefaultDTO> cardinalityDefaultList;
        String cardinalityDefaultStr = JiNanMedicalInsurance.getCardinalityDefault(usersessionUuid, cookie, gridSessionID);
        cardinalityDefaultList =
                JSONObject.parseArray(JSON.parseObject(cardinalityDefaultStr).getString("rows"), QingDaoCardinalityDefaultDTO.class);
        cardinalityDefaultList.forEach(cardinalityDefault -> {
            cardinalityDefault.setXzbz(QdWebSiteSocTypeIndex.find(cardinalityDefault.getXzbz()).getDesc());
            BigDecimal hundred = new BigDecimal("100");
            BigDecimal proportionPersonal = new BigDecimal(cardinalityDefault.getGrjfbl());
            BigDecimal proportionCompany = new BigDecimal(cardinalityDefault.getDwjfbl());
            cardinalityDefault.setGrjfbl(proportionPersonal.multiply(hundred).toString());
            cardinalityDefault.setDwjfbl(proportionCompany.multiply(hundred).toString());
        });
        return cardinalityDefaultList.stream().collect(Collectors.toMap(QingDaoCardinalityDefaultDTO::getXzbz, v -> v));
    }
}
